﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using System.Xml.Linq;
using fbasync.webcomponents;
using fbasync.web.Data;

namespace fbasync.web.Controls
{
    [Serializable]
    public class ApplicationEvent
    {
        public string Value { get; set; }
        public string Text { get; set; }

        public ApplicationEvent(string value, string text)
        {
            Value = value;
            Text = text;
        }
    }

    [Serializable]
    public class ApplicationInfo
    {
        public string Name { get; set; }
        public string FacebookApiKey { get; set; }
        public string FacebookSecret { get; set; }
        public bool IsCustom { get; set; }
        public string SessionKey { get; set; }

        public IList<ApplicationEvent> Events { get; set; }
        
        public ApplicationInfo(string name, string facebookApiKey, string facebookSecret, string sessionKey): 
            this(name, facebookApiKey, facebookSecret, sessionKey,  false)
        {
            
        }

        public ApplicationInfo(string name, string facebookApiKey, string facebookSecret, string sessionKey, bool isCustom)
        {
            Name = name;
            FacebookApiKey = facebookApiKey;
            FacebookSecret = facebookSecret;
            SessionKey = sessionKey;
            IsCustom = isCustom;
        }
    }

    public class ApplicationManagerSectionHandler : IConfigurationSectionHandler
    {
        private const string ConfigGroupName = "templateManager";
        private const string ConfigSectionName = "applications";
        private const string ApplicationNode = "application";
        private const string EventsNode = "events";
        private const string NameAttribute = "name";
        private const string TextAttribute = "text";
        private const string FacebookApiKeyAttribute = "facebookApiKey";
        private const string FacebookSecretAttribute = "facebookSecret";
        private const string InfiniteSessionKeyAttribute = "infiniteSessionKey";

        private static IList<ApplicationInfo> _applications;

        static ApplicationManagerSectionHandler()
        {
            System.Configuration.ConfigurationManager.GetSection(string.Format("{0}/{1}", ConfigGroupName, ConfigSectionName));
        }

        public static IList<ApplicationInfo> Applications
        {
            get { return _applications; }
        }

        #region IConfigurationSectionHandler Members

        private string GetAttributeValue(XmlNode section, string attrName, string defaultValue)
        {
            return section.Attributes[attrName] == null ? defaultValue : section.Attributes[attrName].Value;
        }

        public object Create(object parent, object configContext, XmlNode section)
        {
            _applications = new List<ApplicationInfo>(section.ChildNodes.Count);

            ApplicationInfo appInfo;

            foreach (XmlNode appNode in section.ChildNodes)
            {
                if (!ApplicationNode.Equals(appNode.Name)) continue;

                appInfo = new ApplicationInfo(
                    GetAttributeValue(appNode, NameAttribute, NameAttribute),
                    GetAttributeValue(appNode, FacebookApiKeyAttribute, FacebookApiKeyAttribute),
                    GetAttributeValue(appNode, FacebookSecretAttribute, FacebookSecretAttribute),
                    GetAttributeValue(appNode, InfiniteSessionKeyAttribute, InfiniteSessionKeyAttribute));

                _applications.Add(appInfo);

                foreach (XmlNode child in appNode.ChildNodes)
                {
                    if (EventsNode.Equals(child.Name))
                    {
                        appInfo.Events = new List<ApplicationEvent>();

                        foreach (XmlNode appEvent in child.ChildNodes)
                        {
                            appInfo.Events.Add(new ApplicationEvent(
                                appEvent.Name,
                                GetAttributeValue(appEvent, TextAttribute, appEvent.Name)));
                        }
                    }
                }
            }

            return null;
        }

        #endregion
    }

    public class ApplicationManager
    {
        private static IList<ApplicationInfo> _applications;

        public const string CurrentApplicationSessionKey = "CurrentFacebookApplication";
        public const string CurrentNewStoryTemplateBundleKey = "CurrentNewStoryTemplateBundle";
        public const string CustomApplicationKey = "ApplicationManagerCustomApplication";

        public static IList<ApplicationInfo> Applications
        {
            get
            {
                if (_applications == null) InitApplications();

                return _applications;
            }
        }

        public static ApplicationInfo CurrentApplication
        {
            get 
            {
                if (Applications.Count == 0) return null;

                int appIndex = (null == HttpContext.Current) || (null == HttpContext.Current.Session) ? 
                    0 :
                    ((int?)HttpContext.Current.Session[CurrentApplicationSessionKey]).GetValueOrDefault(0);

                return Applications[appIndex];

            }
        }

        private static void InitApplications()
        {
            _applications = new List<ApplicationInfo>(ApplicationManagerSectionHandler.Applications);

            Pair customAppPair = (Pair)HttpContext.Current.Session[CustomApplicationKey];

            if (null != customAppPair)
            {
                AddCustomApplication(customAppPair.First.ToString(), customAppPair.Second.ToString());
            }
        }

        internal static void SetCurrentApplication(string applicationKey)
        {
            if (String.IsNullOrEmpty(applicationKey)) return;

            for (int appIndex = 0; appIndex <= Applications.Count; appIndex++)
            {
                if (applicationKey.Equals(Applications[appIndex].FacebookApiKey))
                {
                    HttpContext.Current.Session[CurrentApplicationSessionKey] = appIndex;

                    break;
                }
            }
        }

        internal static ApplicationInfo GetApplicationByName(string applicationName)
        {
            if (String.IsNullOrEmpty(applicationName)) return null;

            foreach (ApplicationInfo appInfo in Applications)
            {
                if (applicationName.Equals(appInfo.Name)) return appInfo;
            }

            return null;
        }

        internal static void AddCustomApplication(string apiKey, string secretKey)
        {
            foreach (ApplicationInfo appInfo in Applications)
            {
                if (appInfo.IsCustom)
                {
                    appInfo.FacebookApiKey = apiKey;
                    appInfo.FacebookSecret = secretKey;

                    return;
                }
            }

            Applications.Add(new ApplicationInfo(apiKey.GetHashCode().ToString(), apiKey, secretKey, String.Empty, true));

            HttpContext.Current.Session[CustomApplicationKey] = new Pair(apiKey, secretKey);
        }

        internal static bool IsCustomApplication(string apiKey)
        {
            foreach (ApplicationInfo appInfo in Applications)
            {
                if (appInfo.FacebookApiKey.Equals(apiKey)) return appInfo.IsCustom;
            }

            return false;
        }

        internal static ApplicationInfo GetApplicationByApiKey(string apiKey)
        {
            if (String.IsNullOrEmpty(apiKey)) return null;

            foreach (ApplicationInfo appInfo in Applications)
            {
                if (apiKey.Equals(appInfo.FacebookApiKey)) return appInfo;
            }

            return null;
        }
    }
}
